package memorphic.slide.plugin.wizards;

import memorphic.slide.plugin.generators.ContextTemplate;
import memorphic.slide.plugin.generators.ControllerTemplate;
import memorphic.slide.plugin.generators.SlideBaseTemplate;
import memorphic.slide.plugin.generators.StatesTemplate;

import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.operation.*;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import java.io.*;
import org.eclipse.ui.*;
import org.eclipse.ui.ide.IDE;

/**
 * This is a sample new wizard. Its role is to create a new file 
 * resource in the provided container. If the container resource
 * (a folder or a project) is selected in the workspace 
 * when the wizard is opened, it will accept it as the target
 * container. The wizard creates one file with the extension
 * "mpe". If a sample multi-page editor (also available
 * as a template) is registered for the same extension, it will
 * be able to open it.
 */

public class NewFeatureWizard extends Wizard implements INewWizard {
	
	private enum ContentType {
		CONTEXT_CLASS,
		CONTROLLER_CLASS,
		STATE_CLASS
	}
	
	private NewFeatureWizardPage page;
	private ISelection selection;

	/**
	 * Constructor for NewFeatureWizard.
	 */
	public NewFeatureWizard() {
		super();
		setNeedsProgressMonitor(true);
	}
	
	/**
	 * Adding the page to the wizard.
	 */

	public void addPages() {
		page = new NewFeatureWizardPage(selection);
		addPage(page);
	}

	/**
	 * This method is called when 'Finish' button is pressed in
	 * the wizard. We will create an operation and run it
	 * using wizard as execution context.
	 */
	public boolean performFinish() {
		final IProject project = page.getProject();
		final String projectSrc = page.getProjectSourcePath();
		//final String featureName = page.getFeatureName();
		final String featurePackage = page.getFeaturePackage();
		final String contextClassName = page.getContextClassName();
		final String featureID = page.getFeatureID();
		final String controllerClassName = page.getControllerClassName();
		final String stateClassName = page.getStateClassName();
		final String projectDirectory = page.getProjectDirectory();
		final IFolder sourceFolder = project.getFolder(new Path(projectSrc));
		IRunnableWithProgress op = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				try {
					doFinish(sourceFolder,
							featurePackage,
							featureID,
							contextClassName,
							controllerClassName,
							stateClassName,
							monitor);
				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				} finally {
					monitor.done();
				}
			}
		};
		try {
			getContainer().run(true, false, op);
		} catch (InterruptedException e) {
			return false;
		} catch (InvocationTargetException e) {
			Throwable realException = e.getTargetException();
			MessageDialog.openError(getShell(), "Error", realException.getMessage());
			return false;
		}
		return true;
	}
	
	/**
	 * The worker method. It will find the container, create the
	 * file if missing or just replace its contents, and open
	 * the editor on the newly created file.
	 */

	private void doFinish(
		IFolder sourceFolder,
		String featurePackage,
		String featureID,
		String contextClassName,
		String controllerClassName,
		String stateClassName,
		IProgressMonitor monitor)
		throws CoreException {
		// create a sample file
		monitor.beginTask("Creating " + contextClassName, 2);
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

		IResource resource = createFeatureFolder(featurePackage,sourceFolder, monitor);
		
		IContainer container = (IContainer) resource;
		final IFile contextClassFile = container.getFile(new Path(contextClassName + ".as"));
		final IFile controllerClassFile = container.getFile(new Path(controllerClassName + ".as"));
		final IFile stateClassFile = container.getFile(new Path(stateClassName + ".as"));
		try {
			InputStream contextStream = openContentStream(ContentType.CONTEXT_CLASS,
					featurePackage,
					featureID,
					contextClassName,
					controllerClassName,
					stateClassName);
			InputStream controllerStream = openContentStream(ContentType.CONTROLLER_CLASS,
					featurePackage,
					featureID,
					contextClassName,
					controllerClassName,
					stateClassName);
			InputStream stateStream = openContentStream(ContentType.STATE_CLASS,
					featurePackage,
					featureID,
					contextClassName,
					controllerClassName,
					stateClassName);
			if (contextClassFile.exists()) {
				contextClassFile.setContents(contextStream, true, true, monitor);
			} else {
				contextClassFile.create(contextStream, true, monitor);
			}
			if (controllerClassFile.exists()) {
				controllerClassFile.setContents(controllerStream, true, true, monitor);
			} else {
				controllerClassFile.create(controllerStream, true, monitor);
			}
			if (stateClassFile.exists()) {
				stateClassFile.setContents(stateStream, true, true, monitor);
			} else {
				stateClassFile.create(stateStream, true, monitor);
			}
			contextStream.close();
			controllerStream.close();
			stateStream.close();
		} catch (IOException e) {
		}
		monitor.worked(1);
		monitor.setTaskName("Opening file for editing...");
		getShell().getDisplay().asyncExec(new Runnable() {
			public void run() {
				IWorkbenchPage page =
					PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
				try {
					IDE.openEditor(page, contextClassFile, true);
					IDE.openEditor(page, controllerClassFile, true);
					IDE.openEditor(page, stateClassFile, true);
				} catch (PartInitException e) {
				}
			}
		});
		monitor.worked(1);
	}
	
	private IFolder createFeatureFolder(String featurePackage, IFolder sourceFolder, IProgressMonitor monitor ) throws CoreException
	{
		String[] folders = featurePackage.split("\\.");
		IFolder folder = sourceFolder;
		for (int i = 0; i < folders.length; i++)
		{
			folder = folder.getFolder(folders[i]);
			if (!folder.exists())
			{
				folder.create(false, false, monitor);
			}
		}
		
		return folder;
	}
	
	private String generateCurrentPath(String[] folders, int level)
	{
		String currentPath = folders[1] + "/";
		for (int i = 2; i < level; i++)
		{
			currentPath += "/" + folders[i];
		}
		return currentPath;
	}
	
	/**
	 * We will initialize file contents with a sample text.
	 */

	private InputStream openContentStream(ContentType type,
										  String featurePackage,
										  String featureID,
										  String contextClassName,
										  String controllerClassName,
										  String stateClassName
										  ) {
		String contents;
		SlideBaseTemplate template;
		switch (type)
		{
		case CONTEXT_CLASS:
			template = new ContextTemplate();
			break;
		case CONTROLLER_CLASS:
			template = new ControllerTemplate();
			break;
		case STATE_CLASS:
			template = new StatesTemplate();
			break;
		default:
			return null;
		}
		template.featurePackage = featurePackage;
		template.featureID = featureID;
		template.contextClassName = contextClassName;
		template.controllerClassName = controllerClassName;
		template.stateClassName = stateClassName;
		contents = template.generate(null);
		return new ByteArrayInputStream(contents.getBytes());
	}

	private void throwCoreException(String message) throws CoreException {
		IStatus status =
			new Status(IStatus.ERROR, "memorphic.slide.plugin", IStatus.OK, message, null);
		throw new CoreException(status);
	}

	/**
	 * We will accept the selection in the workbench to see if
	 * we can initialize from it.
	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
	 */
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}
}